﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Implementations;
using MQTTnet.Protocol;
using MQTTnet.Server;
using Newtonsoft.Json.Linq;
using Qianke.Common;
using Qianke.Common.MQTT;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using ScintillaNET;


namespace MqttClient
{
    public partial class MainForm : Form
    {
        private static Inifile.IniApp app = new Inifile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.ini"))["AppConfig"];

        private MqttHelper mqttClient;
        
        // 日志缓冲相关字段
        private readonly ConcurrentQueue<LogEntry> _logQueue = new ConcurrentQueue<LogEntry>();
        private readonly System.Windows.Forms.Timer _logTimer;
        private readonly object _logLock = new object();
        private const int MAX_LOG_LENGTH = 1000000; // 最大日志长度
        private const int LOG_CLEANUP_LENGTH = 800000; // 清理时保留的长度
        private const int LOG_UPDATE_INTERVAL = 100; // 日志更新间隔(毫秒)
        
        // 日志条目结构
        public class LogEntry
        {
            public string FullLog { get; set; } // 完整的日志内容
            public string Topic { get; set; } // MQTT主题
            public string Content { get; set; } // 日志内容（去除时间戳等格式信息）
            public DateTime Timestamp { get; set; } // 时间戳
        }
        
        // 自动滚动状态跟踪字段
        private bool _isUserAtBottom = true; // 用户是否在日志底部，默认为true
        private bool _isUserScrolling = false; // 用户是否正在手动滚动
        
        // 日志过滤器相关字段
        private string _topicFilter = ""; // 主题过滤条件
        private string _contentFilter = ""; // 内容过滤条件
        private bool _topicContains = true; // 主题过滤模式：true=包含，false=不包含
        private bool _contentContains = true; // 内容过滤模式：true=包含，false=不包含

        public MainForm()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            
            // 初始化日志定时器
            _logTimer = new System.Windows.Forms.Timer();
            _logTimer.Interval = LOG_UPDATE_INTERVAL;
            _logTimer.Tick += LogTimer_Tick;
            _logTimer.Start();
        }

        private void SaveConfig()
        {
            app["ServerIP"] = string.Join(",", cbx_Server.Items.Cast<string>());
            app["Port"] = txt_Port.Text;
            app["UserName"] = txt_UserName.Text;
            app["PassWord"] = txt_PassWord.Text;
            app["Topic"] = string.Join(",", cbx_Topic.Items.Cast<string>());
            app["Body"] = HttpUtility.UrlEncode(txt_Body.Text);
            app["Chk16String"] = chk_16String.Checked.ToString();
            app["ChkString"] = chk_String.Checked.ToString();
            app["Chk2String"] = chk_2String.Checked.ToString();
            
            // 保存过滤器配置
            app["TopicFilter"] = txt_TopicFilter.Text;
            app["ContentFilter"] = txt_ContentFilter.Text;
            app["TopicContains"] = radio_TopicContains.Checked.ToString();
            app["ContentContains"] = radio_ContentContains.Checked.ToString();
        }

        private void UpdateCombBoxItems(ComboBox comboBox)
        {
            var currentText = comboBox.Text;
            var p = comboBox.Items.Cast<string>().FirstOrDefault(u => u == comboBox.Text);
            if (p != null)
                comboBox.Items.Remove(p);
            comboBox.Items.Insert(0, currentText);
            comboBox.Text = currentText;
            if (comboBox.Items.Count > 20)
                comboBox.Items.RemoveAt(20);
        }


        private void MainForm_Load(object sender, EventArgs e)
        {
            if (app["ServerIP"] != null)
                cbx_Server.Items.AddRange(app["ServerIP"].Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
            if (app["Topic"] != null)
                cbx_Topic.Items.AddRange(app["Topic"].Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));

            if (cbx_Server.Items.Count > 0)
                cbx_Server.Text = cbx_Server.Items[0] as string;
            if (cbx_Topic.Items.Count > 0)
                cbx_Topic.Text = cbx_Topic.Items[0] as string;
            txt_Port.Text = app["Port"];
            txt_UserName.Text = app["UserName"];
            txt_PassWord.Text = app["PassWord"];
            chk_2String.Checked = app["Chk2String"].ToBoolean(false);
            chk_16String.Checked = app["Chk16String"].ToBoolean(false);
            chk_String.Checked = app["ChkString"].ToBoolean(true);
            cbx_ContextType.SelectedItem = "字符串";
            
            // 加载过滤器配置
            txt_TopicFilter.Text = app["TopicFilter"] ?? "";
            txt_ContentFilter.Text = app["ContentFilter"] ?? "";
            radio_TopicContains.Checked = app["TopicContains"].ToBoolean(true);
            radio_TopicNotContains.Checked = !radio_TopicContains.Checked;
            radio_ContentContains.Checked = app["ContentContains"].ToBoolean(true);
            radio_ContentNotContains.Checked = !radio_ContentContains.Checked;
            
            // 更新过滤器状态
            _topicFilter = txt_TopicFilter.Text.Trim();
            _contentFilter = txt_ContentFilter.Text.Trim();
            _topicContains = radio_TopicContains.Checked;
            _contentContains = radio_ContentContains.Checked;
            
            // 添加实时过滤事件
            txt_TopicFilter.TextChanged += Filter_TextChanged;
            txt_ContentFilter.TextChanged += Filter_TextChanged;
            radio_TopicContains.CheckedChanged += Filter_RadioChanged;
            radio_TopicNotContains.CheckedChanged += Filter_RadioChanged;
            radio_ContentContains.CheckedChanged += Filter_RadioChanged;
            radio_ContentNotContains.CheckedChanged += Filter_RadioChanged;


            txt_Body.Text = HttpUtility.UrlDecode(app["Body"]);

            cbx_Qos.DataSource = Enum.GetValues(typeof(MqttQualityOfServiceLevel))
                .Cast<MqttQualityOfServiceLevel>()
                .Select(u => new
                {
                    Id = u,
                    Name = GetMqttQualityOfServiceLevelName(u),
                }).ToList();

            cbx_Qos.ValueMember = "Id";
            cbx_Qos.DisplayMember = "Name";
            btn_Send.Enabled = false;
            btn_Sub.Enabled = false;
            btn_Cancel.Enabled = false;
            
            // 隐藏原来的TextBox，使用Scintilla.NET（推荐，绝对不会自动换行）
            txt_Message.Visible = false;
            rtb_Message.Visible = false;
            lbx_Message.Visible = false;
            scintilla_Message.Visible = true; // 默认使用Scintilla.NET
            
            // 配置Scintilla.NET用于日志显示
            ConfigureScintillaForLogging();
            
            // 添加滚动事件监听
            SetupScrollEventHandlers();
            
            // 测试Scintilla控件
            TestScintillaControl();
        }

        private string GetMqttQualityOfServiceLevelName(MqttQualityOfServiceLevel level)
        {
            switch (level)
            {
                case MqttQualityOfServiceLevel.AtMostOnce:
                    return "最多一次(0)";
                case MqttQualityOfServiceLevel.AtLeastOnce:
                    return "最少一次(1)";
                case MqttQualityOfServiceLevel.ExactlyOnce:
                    return "只有一次(2)";
            }
            return "";
        }


        /// <summary>
        /// 链接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btn_Conn_Click(object sender, EventArgs e)
        {
            try
            {
                mqttClient = new MqttHelper(cbx_Server.Text, txt_Port.Text.ToInt(0), txt_UserName.Text, txt_PassWord.Text, "MQTT客户端:" + Environment.TickCount);
                await mqttClient.Start();

                btn_Send.Enabled = true;
                btn_Sub.Enabled = true;
                btn_Conn.Enabled = false;
                btn_Cancel.Enabled = true;
                UpdateCombBoxItems(cbx_Server);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private async Task<ReturnInfo> ApplicationMessageReceived(HandParam param)
        {
            var strBuilder = new StringBuilder();
            strBuilder.AppendLine("接收时间:" + DateTime.Now.ToString("HH:mm:ss fff"));
            strBuilder.AppendLine("主题：" + param.Topic + " 等级：" + GetMqttQualityOfServiceLevelName(param.Level) + " 保留：" + param.Retain);
            
            string content = "";
            if (chk_16String.Checked)
            {
                var hexContent = string.Join(" ", param.ByteArray.Select(u => u.ToString("X2")));
                strBuilder.AppendLine("16进制：" + hexContent);
                if (string.IsNullOrEmpty(content)) content = hexContent;
            }
            if (chk_String.Checked)
            {
                try
                {
                    var obj = param.Body.ToObject<JToken>();
                    var stringContent = obj.ToString();
                    strBuilder.AppendLine("字符串：" + stringContent);
                    if (string.IsNullOrEmpty(content)) content = stringContent;
                }
                catch (Exception)
                {
                    var stringContent = param.Body;
                    strBuilder.AppendLine("字符串：" + stringContent);
                    if (string.IsNullOrEmpty(content)) content = stringContent;
                }
            }
            if (chk_2String.Checked)
            {
                var binaryContent = string.Join(" ", param.ByteArray.Select(u => Convert.ToString(u, 2)));
                strBuilder.AppendLine("2进制：" + binaryContent);
                if (string.IsNullOrEmpty(content)) content = binaryContent;
            }

            // 使用高效的WriteLog重载，直接传递主题和内容
            WriteLog(strBuilder.ToString(), param.Topic, content);
            await Task.Delay(0);
            return ReturnInfo.Success;
        }

        /// <summary>
        /// 日志定时器回调方法，批量处理日志消息
        /// </summary>
        private void LogTimer_Tick(object sender, EventArgs e)
        {
            if (_logQueue.IsEmpty) return;

            var logBuilder = new StringBuilder();
            var processedCount = 0;
            const int maxBatchSize = 50; // 每次最多处理50条日志

            // 批量取出日志消息并应用过滤器
            LogEntry logEntry;
            while (_logQueue.TryDequeue(out logEntry) && processedCount < maxBatchSize)
            {
                // 应用过滤器验证
                if (ShouldShowLog(logEntry))
                {
                    logBuilder.AppendLine(logEntry.FullLog);
                }
                processedCount++;
            }

            if (logBuilder.Length > 0)
            {
                // WinForms Timer已经在UI线程中运行，直接更新界面
                UpdateLogDisplay(logBuilder.ToString());
            }
        }

        /// <summary>
        /// 更新日志显示
        /// </summary>
        private void UpdateLogDisplay(string newLogContent)
        {
            lock (_logLock)
            {
                if (scintilla_Message.Visible)
                {
                    // 使用Scintilla.NET显示日志（推荐，绝对不会自动换行）
                    UpdateLogDisplayScintilla(newLogContent);
                }
                else if (lbx_Message.Visible)
                {
                    // 使用ListBox显示日志（绝对不会自动换行）
                    UpdateLogDisplayListBox(newLogContent);
                }
                else
                {
                    // 使用RichTextBox显示日志（支持多行复制）
                    UpdateLogDisplayRichTextBox(newLogContent);
                }
            }
        }



        /// <summary>
        /// 使用Scintilla.NET更新日志显示（推荐，绝对不会自动换行）
        /// </summary>
        private void UpdateLogDisplayScintilla(string newLogContent)
        {
            try
            {
                // 检查控件是否可用
                if (scintilla_Message == null || !scintilla_Message.IsHandleCreated)
                {
                    System.Diagnostics.Debug.WriteLine("Scintilla控件不可用");
                    return;
                }

                // 检查文本长度，如果超过限制则清理
                if (scintilla_Message.TextLength > MAX_LOG_LENGTH)
                {
                    var currentText = scintilla_Message.Text;
                    var startIndex = currentText.Length - LOG_CLEANUP_LENGTH;
                    if (startIndex > 0)
                    {
                        scintilla_Message.Text = currentText.Substring(startIndex);
                    }
                }

                // 临时设置为可写
                scintilla_Message.ReadOnly = false;
                
                // 确保WrapMode为None
                scintilla_Message.WrapMode = WrapMode.None;
                
                // 移动到文本末尾
                scintilla_Message.GotoPosition(scintilla_Message.TextLength);
                
                // 追加新内容
                scintilla_Message.AppendText(newLogContent);
                
                // 只有在用户滚动到底部时才自动滚动
                if (newLogContent.Length > 0 && _isUserAtBottom && !_isUserScrolling)
                {
                    scintilla_Message.GotoPosition(scintilla_Message.TextLength);
                    scintilla_Message.ScrollCaret();
                }
                
                // 恢复只读状态
                scintilla_Message.ReadOnly = true;
            }
            catch (Exception ex)
            {
                // 如果Scintilla操作失败，记录错误但不中断程序
                System.Diagnostics.Debug.WriteLine("Scintilla操作失败: " + ex.Message);
                
                // 尝试使用简单的Text属性设置
                try
                {
                    scintilla_Message.ReadOnly = false;
                    scintilla_Message.Text += newLogContent;
                    scintilla_Message.ReadOnly = true;
                }
                catch (Exception ex2)
                {
                    System.Diagnostics.Debug.WriteLine("Scintilla备用方法也失败: " + ex2.Message);
                }
            }
        }

        /// <summary>
        /// 使用ListBox更新日志显示（推荐，绝对不会自动换行）
        /// </summary>
        private void UpdateLogDisplayListBox(string newLogContent)
        {
            // 检查项目数量，如果超过限制则清理
            if (lbx_Message.Items.Count > 1000) // 限制最多1000行
            {
                while (lbx_Message.Items.Count > 800) // 保留800行
                {
                    lbx_Message.Items.RemoveAt(0);
                }
            }

            // 按行分割内容并添加到ListBox
            var lines = newLogContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var line in lines)
            {
                if (!string.IsNullOrWhiteSpace(line))
                {
                    lbx_Message.Items.Add(line);
                }
            }

            // 只有在用户滚动到底部时才自动滚动
            if (lbx_Message.Items.Count > 0 && _isUserAtBottom && !_isUserScrolling)
            {
                lbx_Message.SelectedIndex = lbx_Message.Items.Count - 1;
                lbx_Message.TopIndex = lbx_Message.Items.Count - 1;
            }
        }

        /// <summary>
        /// 使用RichTextBox更新日志显示（优化版本，彻底禁用自动换行）
        /// </summary>
        private void UpdateLogDisplayRichTextBox(string newLogContent)
        {
            // 检查文本长度，如果超过限制则清理
            if (rtb_Message.TextLength > MAX_LOG_LENGTH)
            {
                var currentText = rtb_Message.Text;
                var startIndex = currentText.Length - LOG_CLEANUP_LENGTH;
                if (startIndex > 0)
                {
                    rtb_Message.Text = currentText.Substring(startIndex);
                }
            }

            // 使用SuspendLayout和ResumeLayout来减少重绘
            rtb_Message.SuspendLayout();
            try
            {
                // 强制确保WordWrap为false
                rtb_Message.WordWrap = false;
                
                // 保存当前选择状态
                int originalStart = rtb_Message.SelectionStart;
                int originalLength = rtb_Message.SelectionLength;
                
                // 移动到文本末尾
                rtb_Message.SelectionStart = rtb_Message.TextLength;
                rtb_Message.SelectionLength = 0;
                
                // 使用SelectedText插入文本，避免自动换行
                rtb_Message.SelectedText = newLogContent;
                
                // 恢复选择状态
                rtb_Message.SelectionStart = originalStart;
                rtb_Message.SelectionLength = originalLength;
                
                // 只有在用户滚动到底部时才自动滚动
                if (newLogContent.Length > 0 && _isUserAtBottom && !_isUserScrolling)
                {
                    rtb_Message.SelectionStart = rtb_Message.TextLength;
                    rtb_Message.ScrollToCaret();
                }
                
                // 再次确保WordWrap为false（防止某些情况下被重置）
                rtb_Message.WordWrap = false;
            }
            finally
            {
                rtb_Message.ResumeLayout();
            }
        }

        /// <summary>
        /// 写入日志（优化版本）
        /// </summary>
        private void WriteLog(string strLog)
        {
            // 创建日志条目
            var logEntry = new LogEntry
            {
                FullLog = strLog,
                Topic = ExtractTopicFromLog(strLog),
                Content = ExtractContentFromLog(strLog),
                Timestamp = DateTime.Now
            };
            
            // 将日志条目加入队列，避免阻塞调用线程
            _logQueue.Enqueue(logEntry);
        }
        
        /// <summary>
        /// 写入带主题和内容的日志（高效版本）
        /// </summary>
        private void WriteLog(string strLog, string topic, string content)
        {
            // 创建日志条目
            var logEntry = new LogEntry
            {
                FullLog = strLog,
                Topic = topic ?? "",
                Content = content ?? "",
                Timestamp = DateTime.Now
            };
            
            // 将日志条目加入队列，避免阻塞调用线程
            _logQueue.Enqueue(logEntry);
        }
        
        /// <summary>
        /// 从日志字符串中提取主题信息
        /// </summary>
        private string ExtractTopicFromLog(string log)
        {
            try
            {
                // 查找"主题："后面的内容
                var topicIndex = log.IndexOf("主题：");
                if (topicIndex >= 0)
                {
                    var startIndex = topicIndex + 3; // "主题："的长度
                    var endIndex = log.IndexOf(" ", startIndex);
                    if (endIndex > startIndex)
                    {
                        return log.Substring(startIndex, endIndex - startIndex);
                    }
                    else if (endIndex == -1)
                    {
                        // 如果后面没有空格，取到行尾
                        var lineEnd = log.IndexOf("\n", startIndex);
                        if (lineEnd > startIndex)
                        {
                            return log.Substring(startIndex, lineEnd - startIndex);
                        }
                        else
                        {
                            return log.Substring(startIndex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("提取主题失败: " + ex.Message);
            }
            return "";
        }
        
        /// <summary>
        /// 从日志字符串中提取内容信息
        /// </summary>
        private string ExtractContentFromLog(string log)
        {
            try
            {
                // 查找"字符串："后面的内容
                var contentIndex = log.IndexOf("字符串：");
                if (contentIndex >= 0)
                {
                    var startIndex = contentIndex + 4; // "字符串："的长度
                    var lineEnd = log.IndexOf("\n", startIndex);
                    if (lineEnd > startIndex)
                    {
                        return log.Substring(startIndex, lineEnd - startIndex);
                    }
                    else
                    {
                        return log.Substring(startIndex);
                    }
                }
                
                // 如果没有找到"字符串："，查找"16进制："后面的内容
                contentIndex = log.IndexOf("16进制：");
                if (contentIndex >= 0)
                {
                    var startIndex = contentIndex + 4; // "16进制："的长度
                    var lineEnd = log.IndexOf("\n", startIndex);
                    if (lineEnd > startIndex)
                    {
                        return log.Substring(startIndex, lineEnd - startIndex);
                    }
                    else
                    {
                        return log.Substring(startIndex);
                    }
                }
                
                // 如果没有找到特定标识，返回整个日志内容
                return log;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("提取内容失败: " + ex.Message);
            }
            return log;
        }



        /// <summary>
        /// 配置Scintilla.NET用于日志显示，绝对不会自动换行
        /// </summary>
        private void ConfigureScintillaForLogging()
        {
            try
            {
                // 基本属性设置
                scintilla_Message.ReadOnly = false; // 先设为可写，后面再设为只读
                scintilla_Message.WrapMode = WrapMode.None; // 禁用自动换行
                scintilla_Message.Font = new Font("Consolas", 9F); // 等宽字体
                
                // 设置颜色主题
                scintilla_Message.StyleResetDefault();
                scintilla_Message.Styles[Style.Default].Font = "Consolas";
                scintilla_Message.Styles[Style.Default].Size = 9;
                scintilla_Message.Styles[Style.Default].BackColor = Color.White;
                scintilla_Message.Styles[Style.Default].ForeColor = Color.Black;
                
                // 禁用行号显示
                scintilla_Message.Margins[0].Width = 0;
                
                // 设置滚动条
                scintilla_Message.ScrollWidth = 1;
                scintilla_Message.ScrollWidthTracking = true;
                
                // 设置制表符宽度
                scintilla_Message.TabWidth = 4;
                
                // 最后设置为只读
                scintilla_Message.ReadOnly = true;
                
                // 测试添加一些初始文本
                scintilla_Message.Text = "MQTT客户端日志显示区域\n";
            }
            catch (Exception ex)
            {
                // 如果Scintilla配置失败，记录错误
                System.Diagnostics.Debug.WriteLine("Scintilla配置失败: " + ex.Message);
            }
        }

        /// <summary>
        /// 配置RichTextBox用于日志显示，彻底禁用自动换行
        /// </summary>
        private void ConfigureRichTextBoxForLogging()
        {
            // 基本属性设置
            rtb_Message.WordWrap = false;
            rtb_Message.ScrollBars = RichTextBoxScrollBars.Both;
            rtb_Message.DetectUrls = false;
            rtb_Message.AutoWordSelection = false;
            rtb_Message.AcceptsTab = false;
            rtb_Message.HideSelection = false;
            
            // 设置最大文本长度
            rtb_Message.MaxLength = 0; // 无限制
            
            // 禁用自动换行的其他设置
            rtb_Message.SelectionIndent = 0;
            rtb_Message.SelectionHangingIndent = 0;
            rtb_Message.SelectionRightIndent = 0;
            
            // 设置字体为等宽字体
            rtb_Message.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular);
        }

        /// <summary>
        /// 切换日志显示组件
        /// </summary>
        /// <param name="componentType">0=Scintilla.NET, 1=ListBox, 2=RichTextBox</param>
        public void SwitchLogDisplayComponent(int componentType)
        {
            // 隐藏所有组件
            scintilla_Message.Visible = false;
            lbx_Message.Visible = false;
            rtb_Message.Visible = false;
            
            switch (componentType)
            {
                case 0: // Scintilla.NET（推荐，绝对不会自动换行）
                    scintilla_Message.Visible = true;
                    scintilla_Message.Text = ""; // 清空
                    ConfigureScintillaForLogging(); // 重新配置
                    break;
                case 1: // ListBox（绝对不会自动换行）
                    lbx_Message.Visible = true;
                    lbx_Message.Items.Clear(); // 清空
                    break;
                case 2: // RichTextBox（支持多行复制）
                    rtb_Message.Visible = true;
                    rtb_Message.Text = ""; // 清空
                    ConfigureRichTextBoxForLogging(); // 重新配置
                    break;
            }
        }

        /// <summary>
        /// 切换日志显示组件（兼容旧版本）
        /// </summary>
        /// <param name="useListBox">true使用ListBox，false使用RichTextBox</param>
        public void SwitchLogDisplayComponent(bool useListBox)
        {
            if (useListBox)
            {
                SwitchLogDisplayComponent(1); // ListBox
            }
            else
            {
                SwitchLogDisplayComponent(2); // RichTextBox
            }
        }

        /// <summary>
        /// 断开重联 链接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async Task OnDisconnected(MqttClientDisconnectedEventArgs e)
        {
            WriteLog("链接断开！！！！");
            WriteLog(e.ToJson());

            btn_Send.Enabled = false;
            btn_Sub.Enabled = false;
            btn_Conn.Enabled = true;
            btn_Cancel.Enabled = false;
            await Task.Delay(0);
        }

        private async void btn_Send_Click(object sender, EventArgs e)
        {
            if (cbx_Topic.Text.IsNullOrEmpty())
            {
                MessageBox.Show("主题不能未空");
                return;
            }

            if (txt_Body.Text.IsNullOrEmpty())
            {
                MessageBox.Show("发送内容不能未空");
                return;
            }

            try
            {
                ReturnInfo result = ReturnInfo.Success;
                switch (cbx_ContextType.SelectedItem.ToString())
                {
                    case "16进制串":
                        //7E 80 00 01 00 00 23 AA 00 01 C1 3D 7E
                        var buffer = Regex.Matches(txt_Body.Text, "([0-9a-zA-Z]{2})").Cast<Match>().Select(u => Convert.ToByte(u.Value, 16)).ToArray();
                        result = await mqttClient.PublishAsync(cbx_Topic.Text, buffer, (MqttQualityOfServiceLevel)cbx_Qos.SelectedValue);
                        break;
                    case "字符串":
                        result = await mqttClient.PublishAsync(cbx_Topic.Text, txt_Body.Text, (MqttQualityOfServiceLevel)cbx_Qos.SelectedValue);
                        break;
                    case "二进制串":
                        MessageBox.Show("暂时不支持");
                        return;
                }

                UpdateCombBoxItems(cbx_Topic);
                WriteLog(result.ToJson());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btn_Sub_Click(object sender, EventArgs e)
        {
            if (cbx_Topic.Text.IsNullOrEmpty())
            {
                MessageBox.Show("主题不能未空");
                return;
            }
            try
            {
                var handler = new SubscribeHandle(cbx_Topic.Text, ApplicationMessageReceived, (MqttQualityOfServiceLevel)cbx_Qos.SelectedValue);
                var result = await mqttClient.SubscribeAsync(handler);
                UpdateCombBoxItems(cbx_Topic);
                if (result.resultcode == "200")
                    WriteLog("订阅主题：" + cbx_Topic.Text + "成功");
                else
                    WriteLog("订阅主题：" + cbx_Topic.Text + "失败：" + result.resultcontent);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            SaveConfig();
            
            // 清理资源
            if (_logTimer != null)
                _logTimer.Dispose();
        }

        private async void btn_Cancel_Click(object sender, EventArgs e)
        {
            if (cbx_Topic.Text.IsNullOrEmpty())
            {
                MessageBox.Show("主题不能未空");
                return;
            }
            try
            {
                await mqttClient.UnsubscribeAsync(cbx_Topic.Text);
                WriteLog("取消订阅：" + cbx_Topic.Text + "成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 设置滚动事件处理器
        /// </summary>
        private void SetupScrollEventHandlers()
        {
            // 为Scintilla添加滚动事件
            scintilla_Message.UpdateUI += Scintilla_UpdateUI;
            
            // 为ListBox添加滚动事件
            lbx_Message.SelectedIndexChanged += ListBox_SelectedIndexChanged;
            lbx_Message.MouseWheel += ListBox_MouseWheel;
            
            // 为RichTextBox添加滚动事件
            rtb_Message.SelectionChanged += RichTextBox_SelectionChanged;
            rtb_Message.MouseWheel += RichTextBox_MouseWheel;
            
            // 为TextBox添加滚动事件（TextBox没有SelectionChanged事件，使用其他事件）
            txt_Message.TextChanged += TextBox_TextChanged;
            txt_Message.MouseWheel += TextBox_MouseWheel;
        }

        /// <summary>
        /// Scintilla更新UI事件处理
        /// </summary>
        private void Scintilla_UpdateUI(object sender, UpdateUIEventArgs e)
        {
            if (e.Change == UpdateChange.VScroll)
            {
                CheckScintillaScrollPosition();
            }
        }

        /// <summary>
        /// 检查Scintilla滚动位置
        /// </summary>
        private void CheckScintillaScrollPosition()
        {
            try
            {
                if (scintilla_Message != null && scintilla_Message.IsHandleCreated)
                {
                    int currentLine = scintilla_Message.LineFromPosition(scintilla_Message.CurrentPosition);
                    int totalLines = scintilla_Message.Lines.Count;
                    
                    // 如果用户在最后几行，认为是在底部
                    _isUserAtBottom = (totalLines - currentLine) <= 3;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("检查Scintilla滚动位置失败: " + ex.Message);
            }
        }

        /// <summary>
        /// ListBox选择改变事件处理
        /// </summary>
        private void ListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            CheckListBoxScrollPosition();
        }

        /// <summary>
        /// ListBox鼠标滚轮事件处理
        /// </summary>
        private void ListBox_MouseWheel(object sender, MouseEventArgs e)
        {
            _isUserScrolling = true;
            // 延迟重置滚动状态
            var timer = new System.Windows.Forms.Timer();
            timer.Interval = 100;
            timer.Tick += (s, args) =>
            {
                timer.Stop();
                timer.Dispose();
                _isUserScrolling = false;
                CheckListBoxScrollPosition();
            };
            timer.Start();
        }

        /// <summary>
        /// 检查ListBox滚动位置
        /// </summary>
        private void CheckListBoxScrollPosition()
        {
            try
            {
                if (lbx_Message != null && lbx_Message.Items.Count > 0)
                {
                    int visibleItems = lbx_Message.ClientSize.Height / lbx_Message.ItemHeight;
                    int lastVisibleIndex = lbx_Message.TopIndex + visibleItems - 1;
                    int lastItemIndex = lbx_Message.Items.Count - 1;
                    
                    _isUserAtBottom = lastVisibleIndex >= lastItemIndex - 1;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("检查ListBox滚动位置失败: " + ex.Message);
            }
        }

        /// <summary>
        /// RichTextBox选择改变事件处理
        /// </summary>
        private void RichTextBox_SelectionChanged(object sender, EventArgs e)
        {
            CheckRichTextBoxScrollPosition();
        }

        /// <summary>
        /// RichTextBox鼠标滚轮事件处理
        /// </summary>
        private void RichTextBox_MouseWheel(object sender, MouseEventArgs e)
        {
            _isUserScrolling = true;
            // 延迟重置滚动状态
            var timer = new System.Windows.Forms.Timer();
            timer.Interval = 100;
            timer.Tick += (s, args) =>
            {
                timer.Stop();
                timer.Dispose();
                _isUserScrolling = false;
                CheckRichTextBoxScrollPosition();
            };
            timer.Start();
        }

        /// <summary>
        /// 检查RichTextBox滚动位置
        /// </summary>
        private void CheckRichTextBoxScrollPosition()
        {
            try
            {
                if (rtb_Message != null)
                {
                    int currentPosition = rtb_Message.SelectionStart;
                    int textLength = rtb_Message.TextLength;
                    
                    // 如果光标在最后10%的文本中，认为是在底部
                    _isUserAtBottom = (textLength - currentPosition) <= (textLength * 0.1);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("检查RichTextBox滚动位置失败: " + ex.Message);
            }
        }

        /// <summary>
        /// TextBox文本改变事件处理
        /// </summary>
        private void TextBox_TextChanged(object sender, EventArgs e)
        {
            CheckTextBoxScrollPosition();
        }

        /// <summary>
        /// TextBox鼠标滚轮事件处理
        /// </summary>
        private void TextBox_MouseWheel(object sender, MouseEventArgs e)
        {
            _isUserScrolling = true;
            // 延迟重置滚动状态
            var timer = new System.Windows.Forms.Timer();
            timer.Interval = 100;
            timer.Tick += (s, args) =>
            {
                timer.Stop();
                timer.Dispose();
                _isUserScrolling = false;
                CheckTextBoxScrollPosition();
            };
            timer.Start();
        }

        /// <summary>
        /// 检查TextBox滚动位置
        /// </summary>
        private void CheckTextBoxScrollPosition()
        {
            try
            {
                if (txt_Message != null)
                {
                    int currentPosition = txt_Message.SelectionStart;
                    int textLength = txt_Message.TextLength;
                    
                    // 如果光标在最后10%的文本中，认为是在底部
                    _isUserAtBottom = (textLength - currentPosition) <= (textLength * 0.1);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("检查TextBox滚动位置失败: " + ex.Message);
            }
        }


        /// <summary>
        /// 判断日志是否应该显示（基于LogEntry的高效过滤）
        /// </summary>
        private bool ShouldShowLog(LogEntry logEntry)
        {
            bool topicMatch = true;
            bool contentMatch = true;

            // 检查主题过滤 - 直接比较主题字段，无需字符串搜索
            if (!string.IsNullOrEmpty(_topicFilter))
            {
                bool containsTopic = !string.IsNullOrEmpty(logEntry.Topic) && 
                                   logEntry.Topic.Contains(_topicFilter);
                topicMatch = _topicContains ? containsTopic : !containsTopic;
            }

            // 检查内容过滤 - 直接比较内容字段，无需字符串搜索
            if (!string.IsNullOrEmpty(_contentFilter))
            {
                bool containsContent = !string.IsNullOrEmpty(logEntry.Content) && 
                                     logEntry.Content.Contains(_contentFilter);
                contentMatch = _contentContains ? containsContent : !containsContent;
            }

            return topicMatch && contentMatch;
        }
        
        /// <summary>
        /// 判断日志是否应该显示（兼容旧版本，基于字符串搜索）
        /// </summary>
        private bool ShouldShowLog(string log)
        {
            bool topicMatch = true;
            bool contentMatch = true;

            // 检查主题过滤
            if (!string.IsNullOrEmpty(_topicFilter))
            {
                bool containsTopic = log.Contains(_topicFilter);
                topicMatch = _topicContains ? containsTopic : !containsTopic;
            }

            // 检查内容过滤
            if (!string.IsNullOrEmpty(_contentFilter))
            {
                bool containsContent = log.Contains(_contentFilter);
                contentMatch = _contentContains ? containsContent : !containsContent;
            }

            return topicMatch && contentMatch;
        }


        /// <summary>
        /// 过滤器文本改变事件
        /// </summary>
        private void Filter_TextChanged(object sender, EventArgs e)
        {
            // 更新过滤器状态
            _topicFilter = txt_TopicFilter.Text.Trim();
            _contentFilter = txt_ContentFilter.Text.Trim();
            
            // 保存配置
            SaveConfig();
        }

        /// <summary>
        /// 过滤器单选按钮改变事件
        /// </summary>
        private void Filter_RadioChanged(object sender, EventArgs e)
        {
            // 更新过滤器状态
            _topicContains = radio_TopicContains.Checked;
            _contentContains = radio_ContentContains.Checked;
            
            // 保存配置
            SaveConfig();
        }

        /// <summary>
        /// 清空日志按钮点击事件
        /// </summary>
        private void btn_ClearLog_Click(object sender, EventArgs e)
        {
            try
            {
                // 清空日志队列
                while (_logQueue.TryDequeue(out _)) { }
                
                // 根据当前显示的组件清空日志
                if (scintilla_Message.Visible)
                {
                    scintilla_Message.ReadOnly = false;
                    scintilla_Message.Text = "";
                    scintilla_Message.ReadOnly = true;
                }
                else if (lbx_Message.Visible)
                {
                    lbx_Message.Items.Clear();
                }
                else if (rtb_Message.Visible)
                {
                    rtb_Message.Text = "";
                }
                else if (txt_Message.Visible)
                {
                    txt_Message.Text = "";
                }
                
                // 重置滚动状态
                _isUserAtBottom = true;
                _isUserScrolling = false;
                
                WriteLog("=== 日志已清空 ===");
                WriteLog("当前时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
            catch (Exception ex)
            {
                MessageBox.Show("清空日志时发生错误: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 测试Scintilla控件是否正常工作
        /// </summary>
        private void TestScintillaControl()
        {
            try
            {
                // 延迟测试，确保控件完全初始化
                var timer = new System.Windows.Forms.Timer();
                timer.Interval = 1000; // 1秒后测试
                timer.Tick += (sender, e) =>
                {
                    timer.Stop();
                    timer.Dispose();
                    
                    try
                    {
                        if (scintilla_Message != null && scintilla_Message.IsHandleCreated)
                        {
                            WriteLog("=== MQTT客户端启动 ===");
                            WriteLog("Scintilla控件测试成功");
                            WriteLog("当前时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        }
                        else
                        {
                            System.Diagnostics.Debug.WriteLine("Scintilla控件未正确初始化");
                        }
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine("Scintilla测试失败: " + ex.Message);
                    }
                };
                timer.Start();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Scintilla测试设置失败: " + ex.Message);
            }
        }
    }
}
